package com.hexinfo.dmpro.monitor.config;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hexinfo.dmpro.common.cache.Cache;
import com.hexinfo.dmpro.common.cache.CacheFactory;
import com.hexinfo.dmpro.common.cache.RedisLock;
import com.hexinfo.dmpro.common.utils.StringUtils;
import com.hexinfo.dmpro.monitor.dao.ClusterWhDao;
import com.hexinfo.dmpro.monitor.domain.ClusterDomain;
import com.hexinfo.dmpro.monitor.model.base.MonitorBaseModel;
import com.hexinfo.dmpro.monitor.model.base.MonitorReq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author peng
 * @date 2021/9/29 14:10
 */
@Component
@Slf4j
public class MonitorCache implements ApplicationRunner {

    private static Cache cache;

    @Autowired
    private ClusterWhDao clusterWhDao;

    @Autowired
    private RedisLock redisLock;

    private static ClusterWhDao clusterWhDaoSta;

    private static RedisLock redisLockSta;

    public MonitorCache(CacheFactory cacheFactory) {
        cache = cacheFactory.createCache();

    }

    /**
     * 项目启动时，初始化参数到缓存
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        MonitorCache.clusterWhDaoSta = this.clusterWhDao;
        MonitorCache.redisLockSta = this.redisLock;
        initHadoopHome();
    }

    /**
     * 解决winutils.exe不存在的问题
     */
    public void initHadoopHome() {
        try {
            File workaround = new File(".");
            System.getProperties().put("hadoop.home.dir", workaround.getAbsolutePath());
            if (new File("./bin").mkdirs()) {
                log.info("mkdirs ./bin finish!");
            }
            if (new File("./bin/winutils.exe").createNewFile()) {
                log.info("createFile ./bin/winutils.exe finish!");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 查寻队列信息
     * @param key
     * @return
     */
    public List<String> getKeys(String key){
        return cache.getKeys(key);
    }



    /**
     * 获取请求实体
     *
     * @param centerId
     * @param clusterFlag
     * @param monitorType
     * @return
     */
    public static List<MonitorReq> getMonitorReq(String centerId, String cmFlag, String clusterFlag, String monitorType) {

        List<MonitorReq> monitorReqList = new ArrayList<>();
        String key = "monitor_info:monitor_clusters_" + centerId + "_" + cmFlag + "_" + clusterFlag + "_" + monitorType;
        Map map = new HashMap();
        map.put("centerId", centerId);
        map.put("cmFlag", cmFlag);
        map.put("clusterFlag", clusterFlag);
        map.put("monitorType", monitorType);
//        try {
//            List<MonitorReq> list = cache.getList(key);
//            if (list != null) {
//                return list;
//            }
//        } catch (Exception e) {
//            log.error(e.toString());
//        }
        List<MonitorBaseModel> monitorBaseModels = clusterWhDaoSta.selCmClusterReq(map);
        if (monitorBaseModels != null && monitorBaseModels.size() > 0) {
            for (MonitorBaseModel monitorBaseModel : monitorBaseModels) {
                MonitorReq monitorReq = new MonitorReq();
                monitorReq.setCenterId(monitorBaseModel.getCenterId());
                monitorReq.setCenterName(monitorBaseModel.getCenterName());
                monitorReq.setCmFlag(monitorBaseModel.getCmFlag());
                monitorReq.setCmName(monitorBaseModel.getCmName());
                monitorReq.setClusterFlag(monitorBaseModel.getClusterFlag());
                monitorReq.setClusterName(monitorBaseModel.getClusterName());
                monitorReq.setUrl(monitorBaseModel.getUrl());
                monitorReq.setOtherParam(monitorBaseModel.getOtherParam());
                monitorReq.setNodeHostName(monitorBaseModel.getHostName());
                monitorReqList.add(monitorReq);
            }
        }
//        try {
//            cache.setList(key, monitorReqList);
//        } catch (Exception e) {
//            log.error(e.toString());
//        }
        return monitorReqList;
    }

    /**
     * 获取中心集群信息
     *
     * @return
     */
    public static Map<String, JSONArray> getCenterCluster(MonitorReq monitorReq) {
        Map<String, JSONArray> clusterMap = new HashMap<>();
        List<MonitorReq> monitorReqs = getClusters(monitorReq.getCenterId());
        JSONArray jsonArray = new JSONArray();
        for (MonitorReq req : monitorReqs) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("key", req.getClusterFlag());
            jsonObject.put("value", req.getClusterName());
            jsonArray.add(jsonObject);
        }
        clusterMap.put("centerClusters", jsonArray);
        return clusterMap;
    }

    /**
     * 获取所有的cm集群信息
     *
     * @param centerId
     * @return
     */
    public static List<MonitorReq> getCms(String centerId) {
        List<MonitorReq> monitorReqList = new ArrayList<>();
        String key = "monitor_info:monitor_cms_" + centerId;
        Map map = new HashMap();
        map.put("centerId", centerId);
        map.put("monitorFlag", "1");
        MonitorBaseModel req = new MonitorBaseModel();
        req.setCenterId(centerId);
        req.setMonitorFlag("1");//cm查询特定条件
//        try {
//            List<MonitorReq> list = cache.getList(key);
//            if (list != null) {
//                return list;
//            }
//        } catch (Exception e) {
//            log.error(e.toString());
//        }
        List<MonitorBaseModel> monitorBaseModels = clusterWhDaoSta.selCmInfo(req);
        if (monitorBaseModels != null && monitorBaseModels.size() > 0) {
            for (MonitorBaseModel monitorBaseModel : monitorBaseModels) {
                MonitorReq monitorReq = new MonitorReq();
                monitorReq.setCenterId(monitorBaseModel.getCenterId());
                monitorReq.setCenterName(monitorBaseModel.getCenterName());
                monitorReq.setCmFlag(monitorBaseModel.getCmFlag());
                monitorReq.setCmName(monitorBaseModel.getCmName());
                monitorReq.setClusterFlag(monitorBaseModel.getClusterFlag());
                monitorReq.setClusterName(monitorBaseModel.getClusterName());
                monitorReq.setUrl(monitorBaseModel.getUrl());
                monitorReq.setOtherParam(monitorBaseModel.getOtherParam());
                monitorReq.setAreaId(monitorBaseModel.getAreaId());
                monitorReq.setSortId(monitorBaseModel.getSortId());
                monitorReqList.add(monitorReq);
            }
        }
//        try {
//            setRedisCache(key, monitorReqList);
//        } catch (Exception e) {
//            log.error(e.toString());
//        }
        return monitorReqList;
    }


    /**
     * 获取所有配置的集群信息  redis key值为  monitor_clusters_中心id
     *
     * @param centerId
     * @return
     */
    public static List<MonitorReq> getClusters(String centerId) {
        List<MonitorReq> monitorReqList = new ArrayList<>();
        String key = "monitor_info:monitor_clusters_" + centerId;
        Map map = new HashMap();
        map.put("centerId", centerId);
        map.put("monitorFlag", "1");//cm查询特定条件
//        try {
//            List<MonitorReq> list = cache.getList(key);
//            if (list != null) {
//                return list;
//            }
//        } catch (Exception e) {
//            log.error(e.toString());
//        }
        List<MonitorBaseModel> monitorBaseModels = clusterWhDaoSta.selCmCluster(map);
        if (monitorBaseModels != null && monitorBaseModels.size() > 0) {
            for (MonitorBaseModel monitorBaseModel : monitorBaseModels) {
                MonitorReq monitorReq = new MonitorReq();
                monitorReq.setCenterId(monitorBaseModel.getCenterId());
                monitorReq.setCenterName(monitorBaseModel.getCenterName());
                monitorReq.setCmFlag(monitorBaseModel.getCmFlag());
                monitorReq.setCmName(monitorBaseModel.getCmName());
                monitorReq.setClusterFlag(monitorBaseModel.getClusterFlag());
                monitorReq.setClusterName(monitorBaseModel.getClusterName());
                monitorReq.setUrl(monitorBaseModel.getUrl());
                monitorReq.setOtherParam(monitorBaseModel.getOtherParam());
                monitorReqList.add(monitorReq);
            }
        }
//        try {
//            setRedisCache(key, monitorReqList);
//        } catch (Exception e) {
//            log.error(e.toString());
//        }
        return monitorReqList;
    }


    /**
     * 获取集群组件的真实名称  redis key值为  monitor_serviceName_中心id
     *
     * @param centerId
     * @return
     */
    public static String getServiceName(String centerId, String cmFlag, String clusterFlag, String monitorType) {
        String serviceName = null;
        String key = "monitor_info:monitor_serviceName_" + centerId + "_" + cmFlag + "_" + clusterFlag + "_" + monitorType;
        Map map = new HashMap();
        map.put("centerId", centerId);
        map.put("cmFlag", cmFlag);
        map.put("clusterFlag", clusterFlag);
        map.put("monitorType", monitorType);
//        try {
//            serviceName = cache.get(key).toString();
//            if (StringUtils.isNotBlank(serviceName)) {
//                return serviceName;
//            }
//        } catch (Exception e) {
//            log.error(e.toString());
//        }
        MonitorBaseModel monitorBaseModel = clusterWhDaoSta.selCmClusterServiceName(map);
        if(monitorBaseModel == null || StringUtils.isBlank(monitorBaseModel.getMonitorFlag())){
            try{
                Thread.sleep(5000);
                monitorBaseModel = clusterWhDaoSta.selCmClusterServiceName(map);
            }catch (Exception e){
                log.error(e.toString());
            }
        }
        //集群是否有相应的yarn、impala服务
        if(monitorBaseModel != null && StringUtils.isNotBlank(monitorBaseModel.getMonitorFlag())) {
            serviceName = monitorBaseModel.getMonitorFlag();
        }else {
            return "";
        }
//        try {
//            cache.set(key, serviceName);
//        } catch (Exception e) {
//            log.error(e.toString());
//        }
        return serviceName;
    }

    private static void setRedisCache(String key, List list) {
        //解决 并发问题
        synchronized (key.intern()) {
            if (cache.getList(key) == null) {
                cache.setList(key, list);
            }
        }
    }

    /**
     * 获取所有配置kafkav 单机集群数据
     *
     * @param centerId
     * @return
     */
    public static List<MonitorReq> getKafkaAloneClusters(String centerId) {
        List<MonitorReq> monitorReqList = new ArrayList<>();
        String key = "monitor_info:monitor_kafka_alone_clusters_" + centerId;
        Map map = new HashMap();
        map.put("centerId", centerId);
        map.put("monitorFlag", "2");//kafka 单机集群查询 为2
        try {
            List<MonitorReq> list = cache.getList(key);
            if (list != null) {
                return list;
            }
        } catch (Exception e) {
            log.error(e.toString());
        }
        List<MonitorBaseModel> monitorBaseModels = clusterWhDaoSta.selCmCluster(map);
        if (monitorBaseModels != null && monitorBaseModels.size() > 0) {
            for (MonitorBaseModel monitorBaseModel : monitorBaseModels) {
                MonitorReq monitorReq = new MonitorReq();
                monitorReq.setCenterId(monitorBaseModel.getCenterId());
                monitorReq.setCenterName(monitorBaseModel.getCenterName());
                monitorReq.setCmFlag(monitorBaseModel.getCmFlag());
                monitorReq.setCmName(monitorBaseModel.getCmName());
                monitorReq.setClusterFlag(monitorBaseModel.getClusterFlag());
                monitorReq.setClusterName(monitorBaseModel.getClusterName());
                monitorReq.setUrl(monitorBaseModel.getUrl());
                monitorReq.setOtherParam(monitorBaseModel.getOtherParam());
                monitorReqList.add(monitorReq);
            }
        }
        try {
            setRedisCache(key, monitorReqList);
        } catch (Exception e) {
            log.error(e.toString());
        }
        return monitorReqList;
    }

    /**
     * 获取主机信息
     *
     * @param centerId
     * @param cmFlag
     * @param clusterFlag
     * @param type        YARN / IMPALA  全部的主机信息
     * @param monitorType monitorType 角色的主机信息
     * @return
     */
    public static List<ClusterDomain> getHostNames(String centerId, String cmFlag, String clusterFlag, String type, String monitorType) {
        List<ClusterDomain> clusterDomainList = new ArrayList<>();
        String key = "monitor_info:monitor_hostname_" + centerId + "_" + cmFlag + "_" + clusterFlag + "_" + type;
        if (StringUtils.isNotBlank(monitorType)) {
            key += "_" + monitorType;
        }
        Map map = new HashMap();
        map.put("centerId", centerId);
        map.put("cmFlag", cmFlag);
        map.put("clusterFlag", clusterFlag);
        map.put("type", type);
        map.put("monitorType", monitorType);
        try {
            List<ClusterDomain> list = cache.getList(key);
            if (list != null) {
                return list;
            }
        } catch (Exception e) {
            log.error(e.toString());
        }
        List<MonitorBaseModel> monitorBaseModels = clusterWhDaoSta.selCmHostName(map);
        if (monitorBaseModels != null && monitorBaseModels.size() > 0) {
            for (MonitorBaseModel monitorBaseModel : monitorBaseModels) {
                ClusterDomain clusterDomain = new ClusterDomain();
                clusterDomain.setHostName(monitorBaseModel.getHostName());
                clusterDomain.setRoleType(monitorBaseModel.getHostJob());
                clusterDomainList.add(clusterDomain);
            }
        }
        try {
            setRedisCache(key, clusterDomainList);
        } catch (Exception e) {
            log.error(e.toString());
        }
        return clusterDomainList;
    }

}
